﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Forums.ForumsClient.Models;
using Microsoft.Forums.SyncService;
using System.Windows.Data;
using Microsoft.Forums.OfflineStore;
using System.Windows.Threading;
using System.Globalization;

namespace Microsoft.Forums.ForumsClient.Controllers
{
    /// <summary>
    /// Controller for the subscribe to forums dialog
    /// </summary>
    public class SubscribeToForumsController
    {

        SubscribeToForumsDataModel subscribeDataModel;
        ISynchronizationController syncController;

        /// <summary>
        ///  Get the application level data Model.
        /// </summary>
        public AppDataModel DataModel
        {
            get;
            private set;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SubscribeToForumsController"/> class.
        /// </summary>
        /// <param name="subscribeModel">The subscribe model.</param>
        public SubscribeToForumsController(SubscribeToForumsDataModel subscribeModel)
        {
            DataModel = AppDataModel.Instance;
            syncController = DataModel.SynchronizationManager.Controller;

            subscribeDataModel = subscribeModel;
            subscribeDataModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SubscribeDataModel_PropertyChanged);
            subscribeDataModel.LocaleCollectionView.CurrentChanged += new EventHandler(LocaleOrBrandChanged);
            subscribeDataModel.BrandsCollectionView.CurrentChanged += new EventHandler(LocaleOrBrandChanged);
        }

        #region Private Methods

        #region Event Handlers
        /// <summary>
        /// Handles the PropertyChanged event of the SubscribeDataModel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        private void SubscribeDataModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
           if ("FilterByText".Equals(e.PropertyName, StringComparison.Ordinal))
            {
                var filterText = subscribeDataModel.FilterByText;
                if (!String.IsNullOrEmpty(filterText))
                {
                    filterText = filterText.ToLower(CultureInfo.CurrentCulture);
                }

                subscribeDataModel.AvailableForumsCollectionView.Filter =
                 delegate(object o)
                 {
                     if (o == null) return false;
                     Forum forum = (Forum)o;
                     return
                         String.IsNullOrEmpty(filterText) ||
                         forum.Name.ToLower(CultureInfo.CurrentCulture).Contains(filterText) ||
                         forum.DisplayName.ToLower(CultureInfo.CurrentCulture).Contains(filterText) ||
                         forum.Description.ToLower(CultureInfo.CurrentCulture).Contains(filterText);

                 };
            }
        }

        /// <summary>
        /// Locale or the brand changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void LocaleOrBrandChanged(object sender, EventArgs e)
        {
            RefreshAvailableForums();
        }
        #endregion

        /// <summary>
        /// Adds a forum to the available forums view if it is not in the preview view
        /// and also not already in the local store
        /// </summary>
        /// <param name="forum">The forum to add</param>
        private void AddToAvailableForumsView(Forum forum)
        {
            var store = DataModel.LocalDataStore;

            if ((!subscribeDataModel.PreviewForumsCollection.Any(f => f.Id == forum.Id) &&
                (!store.Forums.Any(f => f.Id == forum.Id))))
            {
                subscribeDataModel.AvailableForumsCollection.Add(forum);
            }
        }

        #endregion
        /// <summary>
        /// Initializes the data in the background.
        /// </summary>
        public void InitializeData()
        {
            var dispatcher = Dispatcher.CurrentDispatcher;
            System.Threading.ThreadPool.QueueUserWorkItem(
                delegate
                {
                    Locale defaultLocale = null;

                    foreach (KeyValuePair<int, string> pair in syncController.SupportedLocales)
                    {
                        Locale locale = new Locale();
                        locale.LocaleName = pair.Value;
                        locale.LocaleIndex = pair.Key;
                        subscribeDataModel.LocaleCollection.Add(locale);
                        if (pair.Value == Properties.Resources.DefaultLocale)
                        {
                            defaultLocale = locale;
                        }
                    }

                    // Load available Brands collection
                    foreach (string brandName in syncController.SupportedBrands)
                    {
                        Brand brand = new Brand();
                        brand.BrandName = brandName;
                        subscribeDataModel.BrandsCollection.Add(brand);
                    }

                    // Set IsDoneLoading on UI thread 
                    dispatcher.BeginInvoke(
                    DispatcherPriority.ApplicationIdle,
                    (Action)delegate
                    {
                        subscribeDataModel.IsDoneLoading = true;
                        subscribeDataModel.ActiveLocale = defaultLocale;
                    });

                });
        }





        #region Subscribe

        /// <summary>
        /// Gets a value indicating whether you can subscribe to forums.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if you can subscribe to forums; otherwise, <c>false</c>.
        /// </value>
        internal bool CanSubscribeToForums
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Subscribe the selected forums
        /// </summary>
        internal void SubscribeToForums()
        {
            // TODO in M2 add logic to get SyncFrequency
            // If user has set values with Synch Settings Dialog, add all of them
            // to the properties set.
            // Else just add the default SyncFrequency from the DB.
            var forumProperties = new ForumPropertySet() { InitialSyncAge = (int)subscribeDataModel.SyncFromAgeCollectionView.CurrentItem, SyncFrequency = 10 };


            // Subscrribe to each forum in the preview area
            foreach (Forum forum in subscribeDataModel.PreviewForumsCollection)
            {
                syncController.SubscribeToForum(forum, forumProperties);
            }
        }

        #endregion

        #region RemoveFromPreviewArea

        /// <summary>
        /// Gets a value indicating whether you can remove a forum from preview area.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance you can remove a forum from preview area; otherwise, <c>false</c>.
        /// </value>
        internal bool CanRemoveFromPreviewArea
        {
            get
            {
                return subscribeDataModel.PreviewForumsCollectionView.CurrentItem != null;
            }
        }

        /// <summary>
        /// Removes selected forum from preview area.
        /// </summary>
        internal void RemoveFromPreviewArea(Forum selectedForum)
        {
            if (selectedForum != null)
            {
                subscribeDataModel.PreviewForumsCollection.Remove(selectedForum);
                subscribeDataModel.PreviewForumsCollectionView.MoveCurrentToPosition(-1);

                // This will cause the Forum to reappear in the available
                // forums list if it's the current brand selection, not in the preview area and not subscribed)
                if (selectedForum.Locale == subscribeDataModel.ActiveLocale.LocaleName &&
                    selectedForum.Brand == subscribeDataModel.ActiveBrand.BrandName)
                {
                    AddToAvailableForumsView(selectedForum);
                }
            }
        }

        #endregion


        #region RefreshAvaibaleForums

        /// <summary>
        /// Gets a value indicating whether you can refresh available forums.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if you can refresh avaibale forums; otherwise, <c>false</c>.
        /// </value>
        internal bool CanRefreshAvailableForums
        {
            get
            {
                return true;
            }
        }


        /// <summary>
        /// Refreshes the available forums.
        /// </summary>
        internal void RefreshAvailableForums()
        {
            var localCollectionView = subscribeDataModel.LocaleCollectionView;
            var brandsCollectionView = subscribeDataModel.BrandsCollectionView;

            // If brand and locale have both been selelcted, refresh available forums display.
            if (subscribeDataModel.ActiveLocale != null && subscribeDataModel.ActiveBrand != null)
            {
                // Set the labels for the separator bar that reads something like
                // Available Expression (Locale en-US)to which you are not subscribed
                //this.AvailableLabel.Content = Properties.Resources.AvailableLabelContent;
                //this.AvailableBrandForumsLabel.Content = this.BrandComboBox.SelectedItem.ToString();
                //this.ForumsLocaleLabel.Content = Properties.Resources.ForumsLocaleLabelContent;
                //this.SelectedLocaleLabel.Content = this.LocaleComboBox.SelectedItem.ToString();
                //this.NotSubscribedLabel.Content = Properties.Resources.NotSubscribedLabelContent;
                subscribeDataModel.AvailableForumsCollection.Clear();

                // Make API call to get forums 
                foreach (Forum msdnForum in syncController.GetAvailableForums(subscribeDataModel.ActiveBrand.BrandName, subscribeDataModel.ActiveLocale.LocaleIndex))
                {
                    msdnForum.Brand = subscribeDataModel.ActiveBrand.BrandName;
                    msdnForum.Locale = subscribeDataModel.ActiveLocale.LocaleName;

                    AddToAvailableForumsView(msdnForum);

                }
                if (subscribeDataModel.AvailableForumsCollection.Count == 0)
                {
                    //this.AvailableLabel.Content = Properties.Resources.AlternateAvailableLabelContent;
                }
            }
        }

        #endregion

        #region AddToPreviewArea

        /// <summary>
        /// Gets a value indicating whether you can add to preview area.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if you can add to preview area; otherwise, <c>false</c>.
        /// </value>
        internal bool CanAddToPreviewArea
        {
            get
            {
                return subscribeDataModel.AvailableForumsCollectionView.CurrentItem != null;
            }
        }

        /// <summary>
        /// Adds forum to preview area.
        /// </summary>
        internal void AddToPreviewArea(Forum selectedForum)
        {
            var availableForumView = subscribeDataModel.AvailableForumsCollectionView;

            if (selectedForum != null)
            {
                subscribeDataModel.AvailableForumsCollection.Remove(selectedForum);
                subscribeDataModel.PreviewForumsCollection.Add(selectedForum);
                availableForumView.MoveCurrentToPosition(-1);
            }
        }

        #endregion
    }
}
